package com.serialcommunication.gui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;

import javax.swing.Box;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JSeparator;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.text.MaskFormatter;
import static com.serialcommunication.constants.GuiConfiguration.*;
import com.serialcommunication.constants.ActionConstants;
import com.serialcommunication.controller.Coordinator;
import com.serialcommunication.enums.Engine;
import com.serialcommunication.enums.Mode;
import com.serialcommunication.gui.component.DisplayComponent;
import com.serialcommunication.gui.component.FunctionButton;
import com.serialcommunication.gui.component.TextFieldFixedValuesComponent;
import com.serialcommunication.gui.component.LedComponent;
import com.serialcommunication.gui.component.ModeButtonComponent;
import com.serialcommunication.gui.component.TextFieldReadOnlyResetOptionComponent;
import com.serialcommunication.gui.component.TextFieldReadWriteComponent;
import com.serialcommunication.gui.frame.MainFrame;
import com.serialcommunication.interfaces.IAction;
import com.serialcommunication.interfaces.IBaseComponent;

public class Application {

	/* Frames */
	private MainFrame mainFrame;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					Application window = new Application();
					Coordinator.initCommunication();
					window.mainFrame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the application.
	 */
	public Application() {
		try {
			for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
				if ("Nimbus".equals(info.getName())) {
					UIManager.setLookAndFeel(info.getClassName());
					break;
				}
			}
		} catch (Exception e) {
		}
		
		Coordinator.setApplicationWindow(this);
		
		mainFrame = new MainFrame(this);
		mainFrame.setTitle("STMC-GUI v0.1");
		mainFrame.setBounds(0, 0, WINDOW_SIZE.width, WINDOW_SIZE.height);
		mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		mainFrame.setLayout(null);

		initializeEngine1Components();
		initializeEngine2Components();
		initializeEngine3Components();
	}

	@SuppressWarnings("unchecked")
	private void initializeEngine1Components() {
		JSeparator sepHorEngine = new JSeparator();
		JLabel headerEngine = new JLabel("MOTOR 1");
		headerEngine.setBounds(10, 10, 70, headerEngine.getPreferredSize().height);
		sepHorEngine.setBounds(80, 17, 350, 5);
		mainFrame.add(sepHorEngine);
		mainFrame.add(headerEngine);
		
		DisplayComponent voltageComponent = new DisplayComponent(Engine.ENGINE_1, ActionConstants.VOLTAGE,  mainFrame, Color.GREEN,3);
		LedComponent linkOkComponent = new LedComponent(Engine.ENGINE_1, (IAction)ActionConstants.LINK_OK, Color.GREEN, mainFrame,3);
		LedComponent transmitErrorComponent = new LedComponent(Engine.ENGINE_1, (IAction)ActionConstants.TRANSMIT_ERROR, Color.GREEN, mainFrame,3);
		
		ModeButtonComponent rampModeComponent = new ModeButtonComponent(Engine.ENGINE_1, ActionConstants.RAMP_MODE, Mode.RAMP, mainFrame);
		ModeButtonComponent rampSoftModeComponent = new ModeButtonComponent(Engine.ENGINE_1, ActionConstants.RAMP_SOFT_MODE, Mode.RAMP_SOFT, mainFrame);
		ModeButtonComponent velocityModeComponent = new ModeButtonComponent(Engine.ENGINE_1, ActionConstants.VELOCITY_MODE, Mode.VELOCITY, mainFrame);
		
		TextFieldReadWriteComponent xTargetComponent = new TextFieldReadWriteComponent(Engine.ENGINE_1, ActionConstants.X_TARGET, mainFrame, createFormatter("HH HH HH"), true, true, 3, 0x000000, 0x7FFFFF, 3); // HIER NOCH NOCH DIE BIT ANZAHL ANGEGEN UND DANN MAX UND MIN AUSRECHNEN
		TextFieldReadWriteComponent vTargetComponent = new TextFieldReadWriteComponent(Engine.ENGINE_1, ActionConstants.V_TARGET, mainFrame, createFormatter("HH HH"), true, true, 3,  0x000, 0x7FF, 2);
		TextFieldReadWriteComponent aMaxComponent = new TextFieldReadWriteComponent(Engine.ENGINE_1, ActionConstants.A_MAX, mainFrame, createFormatter("HH HH"), false, true, 3,  0x000, 0x7FF, 2);
//		TextFieldReadWriteComponent xActualComponent = new TextFieldReadWriteComponent(Engine.ENGINE_1, (IAction)ActionConstants.X_ACTUAL, mainFrame, createFormatter("HH HH HH"), true, false, true,  0x000000, 0x7FFFFF, 3);
		TextFieldReadWriteComponent vMinComponent = new TextFieldReadWriteComponent(Engine.ENGINE_1, ActionConstants.V_MIN, mainFrame, createFormatter("HH HH"), false, false, 3,  0x000, 0x7FF, 2);
		TextFieldReadWriteComponent vMaxComponent = new TextFieldReadWriteComponent(Engine.ENGINE_1, ActionConstants.V_MAX, mainFrame, createFormatter("HH HH"), false, false, 3,  0x000, 0x7FF, 2);
		
		TextFieldFixedValuesComponent motionCurrentComponent = new TextFieldFixedValuesComponent(Engine.ENGINE_1, ActionConstants.MOTION_CURR, mainFrame, MOTION_CURRENT_VALUE_LIST);
		TextFieldFixedValuesComponent holdCurrentComponent = new TextFieldFixedValuesComponent(Engine.ENGINE_1, ActionConstants.HOLD_CURR, mainFrame, HOLD_CURRENT_VALUE_LIST);
		TextFieldFixedValuesComponent uStepResolutionComponent = new TextFieldFixedValuesComponent(Engine.ENGINE_1, ActionConstants.U_STEP_RESOLUTION, mainFrame, U_STEP_RESOLUTION_VALUE_LIST);
		TextFieldFixedValuesComponent waitTimeComponent = new TextFieldFixedValuesComponent(Engine.ENGINE_1, ActionConstants.WAIT_TIME, mainFrame, WAIT_TIME_VALUE_LIST);
		
		TextFieldReadOnlyResetOptionComponent xActualComponent = new TextFieldReadOnlyResetOptionComponent(Engine.ENGINE_1, (IAction)ActionConstants.X_ACTUAL, mainFrame, createFormatter("HH HH HH"), 0x000000, 0x7FFFFF, 3);
		
		FunctionButton motorGoComponent = new FunctionButton(Engine.ENGINE_1, ActionConstants.MOTOR_GO, mainFrame, 3);
		FunctionButton motorGoRptComponent = new FunctionButton(Engine.ENGINE_1, ActionConstants.MOTOR_GO_RPT, mainFrame, 3);
		FunctionButton motorGoRvsComponent = new FunctionButton(Engine.ENGINE_1, ActionConstants.MOTOR_GO_RVS, mainFrame, 3);
		motorGoComponent.addDependentComponent(motorGoRptComponent);
		motorGoComponent.addDependentComponent(motorGoRvsComponent);
		motorGoRptComponent.addDependentComponent(motorGoComponent);
		motorGoRptComponent.addDependentComponent(motorGoRvsComponent);
		motorGoRvsComponent.addDependentComponent(motorGoComponent);
		motorGoRvsComponent.addDependentComponent(motorGoRptComponent);
		
		FunctionButton stopComponent = new FunctionButton(Engine.ENGINE_1, ActionConstants.MOTOR_STOP, mainFrame, 2);
		FunctionButton stopCeComponent = new FunctionButton(Engine.ENGINE_1, ActionConstants.MOTOR_STOP_CE, mainFrame, 2);
		stopComponent.addDependentComponent(stopCeComponent);
		stopComponent.addDependentComponent(motorGoComponent);
		stopComponent.addDependentComponent(motorGoRptComponent);
		stopComponent.addDependentComponent(motorGoRvsComponent);
		stopCeComponent.addDependentComponent(stopComponent);
		stopCeComponent.addDependentComponent(motorGoComponent);
		stopCeComponent.addDependentComponent(motorGoRptComponent);
		stopCeComponent.addDependentComponent(motorGoRvsComponent);
		
		LedComponent voltageOutOfRangeComponent = new LedComponent(Engine.ENGINE_1, ActionConstants.VOLTAGE_OUT_OF_RANGE, Color.GREEN ,mainFrame, 8);
		LedComponent statusLeftReferenceComponent = new LedComponent(Engine.ENGINE_1, ActionConstants.RSL,Color.RED , mainFrame,8);
		LedComponent statusRightReferenceComponent = new LedComponent(Engine.ENGINE_1, ActionConstants.RSR, Color.RED , mainFrame,8);
		LedComponent targetPositionReachedComponent = new LedComponent(Engine.ENGINE_1, ActionConstants.TARGET_POSITION_REACHED, Color.GREEN , mainFrame,8);
		LedComponent tempToHighWarningComponent = new LedComponent(Engine.ENGINE_1, ActionConstants.OVER_TEMP_WARNING, Color.GREEN , mainFrame,8);
		LedComponent tempToHighShutdownComponent = new LedComponent(Engine.ENGINE_1, ActionConstants.OVER_TEMP_SHUTDOWN, Color.GREEN,mainFrame,8);
		LedComponent motorBlockedComponent = new LedComponent(Engine.ENGINE_1, ActionConstants.MOTOR_BLOCKED, Color.GREEN, mainFrame,8);
		LedComponent motorStillComponent = new LedComponent(Engine.ENGINE_1, (IAction)ActionConstants.MOTOR_NOT_MOVING, Color.GREEN , mainFrame,8);
		
//		LedComponent voltageOutOfRangeComponent2 = new LedComponent(Engine.ENGINE_1, ActionConstants.VOLTAGE_OUT_OF_RANGE, mainFrame, 8);
//		LedComponent statusLeftReferenceComponent2 = new LedComponent(Engine.ENGINE_1, ActionConstants.RSL, mainFrame,8);
//		LedComponent statusRightReferenceComponent2 = new LedComponent(Engine.ENGINE_1, ActionConstants.RSR, mainFrame,8);
//		LedComponent targetPositionReachedComponent2 = new LedComponent(Engine.ENGINE_1, ActionConstants.TARGET_POSITION_REACHED, mainFrame,8);
//		LedComponent tempToHighWarningComponent2 = new LedComponent(Engine.ENGINE_1, ActionConstants.OVER_TEMP_WARNING, mainFrame,8);
//		LedComponent tempToHighShutdownComponent2 = new LedComponent(Engine.ENGINE_1, ActionConstants.OVER_TEMP_SHUTDOWN, mainFrame,8);
//		LedComponent motorBlockedComponent2 = new LedComponent(Engine.ENGINE_1, ActionConstants.MOTOR_BLOCKED, mainFrame,8);
//		LedComponent motorStillComponent2 = new LedComponent(Engine.ENGINE_1, (IAction)ActionConstants.MOTOR_NOT_MOVING, mainFrame,8);
		
		mainFrame.rampModeComponents_Engine1.add(xTargetComponent);
		mainFrame.rampModeComponents_Engine1.add(vMinComponent);
		mainFrame.rampModeComponents_Engine1.add(aMaxComponent);
		mainFrame.rampModeComponents_Engine1.add(vMaxComponent);
		mainFrame.rampModeComponents_Engine1.add(xActualComponent);
		mainFrame.velocityModeComponents_Engine1.add(vTargetComponent);
		mainFrame.velocityModeComponents_Engine1.add(aMaxComponent);
		
		JSeparator sepHorEngine2 = new JSeparator();
		sepHorEngine2.setSize(415, 1);
		sepHorEngine2.setOpaque(true);
		sepHorEngine2.setBackground(Color.GRAY);

		JSeparator sepHorEngine3 = new JSeparator();
		sepHorEngine3.setSize(415, 1);
		sepHorEngine3.setOpaque(true);
		sepHorEngine3.setBackground(Color.GRAY);
		
		JSeparator sepHorEngine4 = new JSeparator();
		sepHorEngine4.setSize(415, 1);
		sepHorEngine4.setOpaque(true);
		sepHorEngine4.setBackground(Color.GRAY);
		
		JSeparator sepHorEngine5 = new JSeparator();
		sepHorEngine5.setSize(415, 1);
		sepHorEngine5.setOpaque(true);
		sepHorEngine5.setBackground(Color.GRAY);
		
		JSeparator sepHorEngine6 = new JSeparator();
		sepHorEngine6.setSize(415, 1);
		sepHorEngine6.setOpaque(true);
		sepHorEngine6.setBackground(Color.GRAY);
		
		mainFrame.addComponent("1", 1, voltageComponent);
		mainFrame.addComponent("1", 1, linkOkComponent);
		mainFrame.addComponent("1", 1, transmitErrorComponent);
		
		mainFrame.addComponent("1", 2, sepHorEngine2);
		
		mainFrame.addComponent("1", 3, rampModeComponent);
		mainFrame.addComponent("1", 3, rampSoftModeComponent);
		mainFrame.addComponent("1", 3, velocityModeComponent);
		
		mainFrame.addComponent("1", 4, sepHorEngine3);
		
		mainFrame.addComponent("1", 5, xTargetComponent);
		mainFrame.addComponent("1", 5, aMaxComponent);
		mainFrame.addComponent("1", 5, vTargetComponent);
		
		mainFrame.addComponent("1", 6, xActualComponent)
		;
		mainFrame.addComponent("1", 6, vMinComponent);
		mainFrame.addComponent("1", 6, vMaxComponent);
		
		mainFrame.addComponent("1", 7, sepHorEngine4);
		
		mainFrame.addComponent("1", 8, motionCurrentComponent);
		mainFrame.addComponent("1", 8, holdCurrentComponent);
		mainFrame.addComponent("1", 8, uStepResolutionComponent);
		mainFrame.addComponent("1", 8, waitTimeComponent);
		
		mainFrame.addComponent("1", 9, sepHorEngine5);
		
		mainFrame.addComponent("1", 10, motorGoComponent);
		mainFrame.addComponent("1", 10, motorGoRptComponent);
		mainFrame.addComponent("1", 10, motorGoRvsComponent);
		
		mainFrame.addComponent("1", 11, stopComponent);
		mainFrame.addComponent("1", 11, stopCeComponent);
		
		mainFrame.addComponent("1", 12, sepHorEngine6);
		
		mainFrame.addComponent("1", 13, voltageOutOfRangeComponent);
		mainFrame.addComponent("1", 13, statusLeftReferenceComponent);
		mainFrame.addComponent("1", 13, statusRightReferenceComponent);
		mainFrame.addComponent("1", 13, targetPositionReachedComponent);
		mainFrame.addComponent("1", 13, tempToHighWarningComponent);
		mainFrame.addComponent("1", 13, tempToHighShutdownComponent);
		mainFrame.addComponent("1", 13, motorBlockedComponent);
		mainFrame.addComponent("1", 13, motorStillComponent);
		
//		mainFrame.addComponent("1", 14, voltageOutOfRangeComponent2);
//		mainFrame.addComponent("1", 14, statusLeftReferenceComponent2);
//		mainFrame.addComponent("1", 14, statusRightReferenceComponent2);
//		mainFrame.addComponent("1", 14, targetPositionReachedComponent2);
//		mainFrame.addComponent("1", 14, tempToHighWarningComponent2);
//		mainFrame.addComponent("1", 14, tempToHighShutdownComponent2);
//		mainFrame.addComponent("1", 14, motorBlockedComponent2);
//		mainFrame.addComponent("1", 14, motorStillComponent2);
		
		addMenu();
	}

	private void initializeEngine2Components() {
		JSeparator sepHorEngine = new JSeparator();
		JLabel headerEngine = new JLabel("MOTOR 2");
		headerEngine.setBounds(450, 10, 70, headerEngine.getPreferredSize().height);
		sepHorEngine.setBounds(520, 17, 350, 5);
		mainFrame.add(sepHorEngine);
		mainFrame.add(headerEngine);
	}

	private void initializeEngine3Components() {
		JSeparator sepHorEngine = new JSeparator();
		JLabel headerEngine = new JLabel("MOTOR 3");
		headerEngine.setBounds(900, 10, 70, headerEngine.getPreferredSize().height);
		sepHorEngine.setBounds(970, 17, 350, 5);
		mainFrame.add(sepHorEngine);
		mainFrame.add(headerEngine);
	}
	
	public void linkOk() {
		mainFrame.linkOk();
	}
	
	public void linkNotOk() {
		mainFrame.linkNotOk();
	}
	
	/**
	 * Searches all Panels for a distinct Component with string s as indicator
	 * @param engine
	 * @param s
	 * @return
	 */
	public IBaseComponent getComponentByName(String engine, String s) {
		return null;
	}

	private MaskFormatter createFormatter(String s) {
		MaskFormatter formatter = null;
		try {
			formatter = new MaskFormatter(s);
		} catch (java.text.ParseException exc) {
			System.err.println("formatter is bad: " + exc.getMessage());
			System.exit(-1);
		}
		formatter.setPlaceholderCharacter('0');
		return formatter;
	}
	
	private void addMenu() {
		//Create a menu bar  
		JMenuBar frameMenuBar=new JMenuBar();  
		
		//Create first menu in menubar  
		JMenu menu1=new JMenu("Menu1");  
		  
		//Create second menu in menubar  
		JMenu menu2=new JMenu("Menu2");  
		  
		//Create third menu in menubar  
		JMenu menu3=new JMenu("Menu3");  
		  
		//Create menu that will be add into third menu  
		JMenu menu3_internalMenu1=new JMenu("Menu3_Menu1");  
		  
		//Create first menu item for first menu  
		JMenuItem menuItem1=new JMenuItem("Menu1_MenuItem1");  
		  
		//Create first menu item for second menu  
		JMenuItem menuItem2=new JMenuItem("Menu2_MenuItem1");  
		  
		//Create second menu item for second menu  
		JMenuItem menuItem3=new JMenuItem("Menu2_MenuItem2");  
		  
		//Create first menu item for third menu  
		JMenuItem menuItem4=new JMenuItem("Menu3_MenuItem1");  
		  
		//Create menu item that will be add into internal menu in third menu  
		JMenuItem menuItem5=new JMenuItem("Menu3_Menu1_MenuItem1");  
		  
		//add first menu item into first menu  
		menu1.add(menuItem1);  
		  
		//add first menu item into second menu  
		menu2.add(menuItem2);  
		  
		//add second menu item into second menu  
		menu2.add(menuItem3);  
		  
		//add first menu item into third menu  
		menu3.add(menuItem4);  
		  
		//add internal menu into third menu  
		menu3.add(menu3_internalMenu1);  
		  
		//add menu item into internal menu  
		menu3_internalMenu1.add(menuItem5);  
		  
		//add first menu into menu bar  
		frameMenuBar.add(menu1);  
		  
		//add second menu into menu bar  
		frameMenuBar.add(menu2);  
		  
		//add third menu into menu bar  
		frameMenuBar.add(menu3);  
		
		frameMenuBar.add(Box.createHorizontalGlue());
		JLabel label = new JLabel("test");
		label.setBounds(300, 0, 100, 10);
//		frameMenuBar.add(connectionTestComponent.getTextLabel());
//		frameMenuBar.add(connectionTestComponent.getColorLabel());
		  
		//Set menu bar for JFrame  
		mainFrame.setJMenuBar(frameMenuBar);  
	}
}
